﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Xml.Serialization; /* for XML serialization */
using System.IO;
using System.Collections;

namespace AcmeSportsStore
{
    public partial class SportsView : Form
    {
        private LayoutController mLayoutController = null;
        private PasswordView passwordForm;            
        private NewPasswordView newPasswordForm;

        /*
         * <code remarks="the following fields store the information about
         *  the configuration file, the data to be seralized to the
         *  configuration file, and any other data that is related to it; 
         *  to make the type serializable, it must be declared public and 
         *  qualified by a 'Serializable' attribute "
         *  >
         */

        [Serializable()]
        public struct DataFilesInfo
        {
            public string SportsItemsFile;
            public string CustomersFile;
            public string PurchasedItemsFile;

            /*
             * xml-serializable types need to have a parameterless constructor
             * however all structs already have such a constructor by default
             * and it cannot be explicitly declared
             */

            public DataFilesInfo(string sportsItemsFile, string customersFile, 
                string purchasedItemsFile)
            {
                SportsItemsFile = sportsItemsFile;
                CustomersFile = customersFile;
                PurchasedItemsFile = purchasedItemsFile;
            }
        }

        private DataFilesInfo mDataFilesInfo;

        /*
         * </code>
         */

        private enum SportsItemsOrder
        {
            ById = 0,
            ByName,
            ByDescription,
            ByPrice
        }

        private SportsItemsOrder mSportsItemsOrder;

        private enum CustomersOrder
        { 
            ById = 0,
            ByName,
            ByAddress,
            ByPhone
        }

        private CustomersOrder mCustomersOrder;

        /*
         * <code remarks = "indexed data">
         */
        SportsStore mSportsStore;
        Customers mCustomers;
        PurchasedStore mPurchasedStore;

        /*
         * </code>
         */

        Dictionary<string, Image> mImageDictionary = new Dictionary<string, Image>();

        /*
         * avoid unnecessary mapping in selections
         */
        bool mNoSelectBack = false;

        /* 
         * Constructor
         */ 
        public SportsView()
        {
            InitializeComponent();
        }

        /*
         * <code comments = "set properties of the following 
         * tools for 'Enable' function">
         */
        public TabControl MainTabControl
        {
            get { return tabctlMain; }
        }

        public ToolStripMenuItem MainMenuFile
        {
            get { return MenuFile; }
        }

        public ToolStripMenuItem MainMenuEdit
        {
            get { return MenuEdit; }
        }

        public ToolStripMenuItem MainMenuHelp
        {
            get { return MenuHelp; }
        }

        public ToolStripMenuItem MainMenuLogin
        {
            get { return Login_MenuLog; }
        }

        public ToolStripMenuItem MainMenuLogoff
        {
            get { return Logoff_MenuLog; }
        }

        public ToolStripStatusLabel StatusLbl1
        {
            get { return statusLabel1; }
        }

        public ToolStripStatusLabel StatusLbl2
        {
            get { return statusLabel2; }
        }

        /*
         * </code>
         */

        private void SportsView_Load(object sender, EventArgs e)
        {
            mLayoutController = new LayoutController(this.tabctlMain);
            passwordForm = new PasswordView();
            newPasswordForm = new NewPasswordView();
             
            /*
             * set map from name of sports item to image
             */
            InitializeImages();

            /*
             * <code comments = "setup the file dialogs">
             */

            /*
             * we need to have the dialog prompt the user when it's about
             * to overwrite an existing file.
             */
            SaveFileDlg.OverwritePrompt = true;

            /*
             * the dialog box adds a "xml" as default extention when user
             * doesn't specify it.
             */
            SaveFileDlg.DefaultExt = "xml";
            SaveFileDlg.AddExtension = true;
            /*
             * we have to put a vertical bar at the end
             */
            SaveFileDlg.Filter = "XML Files(*.xml)|*.xml";

            OpenFileDlg.Filter = "XML Files(*.xml)|*.xml";
            /*
             * </code>
             */

            /*
             * <code remarks = "default values for fields in the data files pack;
             *  by default the program uses relative paths for these files (
             *  relative to where the project file is located">
             */

            // currently there are no default project settings

            /*
             * </code>
             */

            SetToLogoffState();

        }

        private void InitializeImages()
        {
            mImageDictionary.Clear();

            // images are loaded from the resource
            // use dictionary for mapping from product name to preview image
            mImageDictionary.Add("Basket ball", AcmeSportsStore.Properties.Resources.M0001_basketball);
            mImageDictionary.Add("Net ball", AcmeSportsStore.Properties.Resources.M0002_netball);
            mImageDictionary.Add("Soccer ball", AcmeSportsStore.Properties.Resources.M0003_soccer);
            mImageDictionary.Add("Boxing gloves", AcmeSportsStore.Properties.Resources.M0004_boxingGloves);
            mImageDictionary.Add("Boxing mitts", AcmeSportsStore.Properties.Resources.M0005_boxMitts);
            mImageDictionary.Add("Cycling helmet", AcmeSportsStore.Properties.Resources.M0006_helmet);
            mImageDictionary.Add("Chess Board", AcmeSportsStore.Properties.Resources.M0007_chess);
        }

        private void btnSportItem_Click(object sender, EventArgs e)
        {
            /*
             * select the 2nd tab
             */
            tabctlMain.SelectedIndex = 1;
        }

        private void btnCustomer_Click(object sender, EventArgs e)
        {
            /*
             * select the 3rd tab
             */
            tabctlMain.SelectedIndex = 2;
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }


        private void cmbItemID_SelectedIndexChanged(object sender, EventArgs e)
        {
            string selText = (string)this.cmbItemID.SelectedItem;

            if (!mNoSelectBack)
            {
                int index = this.mSportsStore.GetIndexForId(new SportsItem(selText, null, null, 0));
                mNoSelectBack = true;
                this.lstItems.SelectedIndex = index;
                mNoSelectBack = false;
            }
        }

        private void cmbCustomerID_SelectedIndexChanged(object sender, EventArgs e)
        {
            int selText = (int)this.cmbCustomerID.SelectedItem;

            if (!mNoSelectBack)
            {
                int index = this.mCustomers.GetIndexForId(new CustomersItem(selText, null, null, 0));
                mNoSelectBack = true;
                this.listCustomers.SelectedIndex = index;
                mNoSelectBack = false;
            }
        }

        private void btnHomeFromTab2_Click(object sender, EventArgs e)
        {
            /*
             *  go back to the home page
             */
            this.tabctlMain.SelectedIndex = 0;
        }

        private void btnHomeFromTab3_Click(object sender, EventArgs e)
        {
            /*
             *  go back to the home page
             */
            this.tabctlMain.SelectedIndex = 0;
        }

        private void EnableMenuItems(bool enabled)
        {
            this.MainTabControl.Enabled = enabled;
            this.MainMenuFile.Enabled = enabled;
            this.MainMenuEdit.Enabled = enabled;
            this.MainMenuHelp.Enabled = enabled;
            this.MainMenuLogin.Enabled = enabled;
            this.MainMenuLogoff.Enabled = enabled;
            this.toolStripMenuItem3.Enabled = enabled;
            this.toolStripMenuItem4.Enabled = enabled;
        }

        private void Admin_MenuLogin_Click(object sender, EventArgs e)
        {
            DialogResult dr = passwordForm.ShowDialog(this);
            string loginName = passwordForm.LoginName;
            if (dr == DialogResult.OK)
            {
                EnableMenuItems(true);
                this.MainMenuLogin.Enabled = false;
                this.StatusLbl1.Text = "You've logged in as:\t" + loginName;

                /*
                 * create context for the user
                 */

                if (!string.IsNullOrEmpty(AccountsStore.DataSetFilePath))
                {
                    LoadDatasetFromXml(AccountsStore.DataSetFilePath);
                }
            }
            // in this case, the program just ignores other return values
        }

        private void SportsView_Resize(object sender, EventArgs e)
        {
            if (mLayoutController != null)
            {
                mLayoutController.UpdateAfterResizing();
            }
        }

        private void SetToLogoffState()
        {
            EnableMenuItems(false);
            Login_MenuLog.Enabled = true;
            statusLabel1.Text = " ";

            /*
             * go back to home page after logoff
             */
            tabctlMain.SelectedIndex = 0;

            /*
             * clear up everything
             */
            lstItems.Items.Clear();
            listCustomers.Items.Clear();
            cmbItemID.Items.Clear();
            cmbCustomerID.Items.Clear();
            cmbCustomerID_tabCustActs.Items.Clear();
            txtItemDetails.Text = "";
            mSportsItemsOrder = SportsItemsOrder.ById;
            // TODO: ....
        }

        private void Logoff_MenuLog_Click(object sender, EventArgs e)
        {
            SetToLogoffState();
        }

        private void Exit_MenuLog_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ChPassWord_MenuEdit_Click(object sender, EventArgs e)
        {
            newPasswordForm.ShowDialog(this);
        }

        private void ReloadSportsItems()
        {
            /*
             * clear the listbox items first
             */
            this.lstItems.Items.Clear();

            /*
             * select the items in specific order
             */
            if (mSportsItemsOrder == SportsItemsOrder.ById)
            {
                for (int i = 0; i < mSportsStore.Count; i++)
                {
                    SportsItem sportsItem = mSportsStore.GetItemByIndexForId(i);
                    this.lstItems.Items.Add(sportsItem.Id + "; " + sportsItem.Name
                        + "; " + sportsItem.PriceString);
                }
            }
            else if (mSportsItemsOrder == SportsItemsOrder.ByName)
            {
                for (int i = 0; i < mSportsStore.Count; i++)
                {
                    SportsItem sportsItem = mSportsStore.GetItemByIndexForName(i);
                    this.lstItems.Items.Add(sportsItem.Id + "; " + sportsItem.Name
                        + "; " + sportsItem.PriceString);
                }
            }
            else if (mSportsItemsOrder == SportsItemsOrder.ByPrice)
            {
                for (int i = 0; i < mSportsStore.Count; i++)
                {
                    SportsItem sportsItem = mSportsStore.GetItemByIndexForPrice(i);
                    this.lstItems.Items.Add(sportsItem.Id + "; " + sportsItem.Name
                        + "; " + sportsItem.PriceString);
                }
            }

            /*
             * set the combo box for id unselected
             */
            cmbItemID.SelectedIndex = -1;
        }

        private void ReloadCustomersItems()
        {
            /*
             * clear the listbox items first
             */
            this.listCustomers.Items.Clear();

            /*
             * select the items in specific order
             */
            if(mCustomersOrder == CustomersOrder.ById )
            {
                for (int i = 0; i < mCustomers.Count; i++)
                {
                    CustomersItem customersItem = mCustomers.GetItemByIndexerForId(i);
                    this.listCustomers.Items.Add(customersItem.CustId + ";" + customersItem.CustName
                        + "; " + customersItem.CustAddress + ";" + customersItem.PhoneToString(customersItem.CustPhone));
                }
            }
            else if (mCustomersOrder == CustomersOrder.ByName )
            {
                for (int i = 0; i < mCustomers.Count; i++)
                {
                    CustomersItem customersItem = mCustomers.GetItemByIndexerForName(i);
                    this.listCustomers.Items.Add(customersItem.CustName + ";" + customersItem.CustId
                        + "; " + customersItem.CustAddress + ";" + customersItem.PhoneToString(customersItem.CustPhone));
                }
            }

            else if (mCustomersOrder == CustomersOrder.ByAddress)
            {
                for (int i = 0; i < mCustomers.Count; i++)
                {
                    CustomersItem customersItem = mCustomers.GetItemByIndexerForAddress(i);
                    this.listCustomers.Items.Add(customersItem.CustAddress + ";" + customersItem.CustId
                        + "; " + customersItem.CustName + ";" + customersItem.PhoneToString(customersItem.CustPhone));
                }
            }

            /*
             * set the combo box for id unselected
             */
            cmbCustomerID.SelectedIndex = -1;
        }

        private void ReloadCustActivities()
        {
            //reset the index value
            cmbCustomerID_tabCustActs.SelectedIndex = -1;
        }

        private void LoadDatasetFromXml(string xmlFilePath)
        {
            /*
             * update the current dataset file path of the user account
             */
            AccountsStore.DataSetFilePath = xmlFilePath;

            string xmlDir = Path.GetDirectoryName(xmlFilePath);
            string xmlFileWithoutExt = Path.GetFileNameWithoutExtension(xmlFilePath);

            string dataFileFolder = Path.Combine(xmlDir, xmlFileWithoutExt);

            XmlSerializer xmlSerializer = new XmlSerializer(typeof(DataFilesInfo));

            try
            {
                using (FileStream fs = new FileStream(xmlFilePath, FileMode.Open))
                {
                    this.mDataFilesInfo = (DataFilesInfo)xmlSerializer.Deserialize(fs);
                }

                string sportsItemsFilePath = Path.Combine(dataFileFolder, 
                    this.mDataFilesInfo.SportsItemsFile);
                string customersFilePath = Path.Combine(dataFileFolder,
                    this.mDataFilesInfo.CustomersFile);
                string purchasedItems = Path.Combine(dataFileFolder,
                    this.mDataFilesInfo.PurchasedItemsFile);

                using (StreamReader srSportsItems = new StreamReader(sportsItemsFilePath))
                using (StreamReader srCustomers = new StreamReader(customersFilePath))
                using (StreamReader srPurchasedItems = new StreamReader(purchasedItems))
                {
                    FileReader fr = new FileReader(srSportsItems, srCustomers, srPurchasedItems);
                    mSportsStore = fr.ReadSportsItems();
                    mCustomers = fr.ReadCustomers();
                }

                /*
                 * set the order type first
                 * it will determine how items are loaded into the listbox
                 */
                mSportsItemsOrder = SportsItemsOrder.ById;
                ReloadSportsItems();
                mCustomersOrder = CustomersOrder.ById;
                ReloadCustomersItems();

                /*
                 * load ids to the combobox
                 */
                for (int i = 0; i < mSportsStore.Count; i++)
                {
                    SportsItem item = mSportsStore.GetItemByIndexForId(i);
                    cmbItemID.Items.Add(item.Id);
                }

                for (int i = 0; i < mCustomers.Count; i++)
                {
                    CustomersItem cItem = mCustomers.GetItemByIndexerForId(i);
                    cmbCustomerID.Items.Add(cItem.CustId);
                    cmbCustomerID_tabCustActs.Items.Add(cItem.CustId);
                }

                
            }

            catch (Exception)
            {
                MessageBox.Show("Oops! An error occurred during loading the project file.", this.Text);
                /*
                 * since the loading is not successful
                 * set the dataset file path for the user to null
                 */
                AccountsStore.DataSetFilePath = null;
            }
        }

        /*
         * load the dataset
         */
        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            DialogResult dr = OpenFileDlg.ShowDialog();

            if (dr == DialogResult.OK)
            {
                /*
                 * a file is selected to be opened
                 */
                LoadDatasetFromXml(OpenFileDlg.FileName);
            }
        }

        private void SaveProjectAtSpecificLocation()
        {
            DialogResult dr = SaveFileDlg.ShowDialog();
            if (dr == DialogResult.OK)
            {
                string xmlFilePath = SaveFileDlg.FileName;
                string xmlDir = Path.GetDirectoryName(xmlFilePath);
                string xmlFileWithoutExt = Path.GetFileNameWithoutExtension(xmlFilePath);

                string dataFileFolder = Path.Combine(xmlDir, xmlFileWithoutExt);
                if (!Directory.Exists(dataFileFolder))
                {
                    DirectoryInfo dirInfo = Directory.CreateDirectory(dataFileFolder);
                }

                /*
                 * a destination file that is specified to be saved to
                 */
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(DataFilesInfo));

                using (FileStream fs = new FileStream(xmlFilePath, FileMode.Create))
                {
                    xmlSerializer.Serialize(fs, mDataFilesInfo);
                }

                if (string.IsNullOrEmpty(mDataFilesInfo.SportsItemsFile))
                {
                    mDataFilesInfo.SportsItemsFile = "sportsItems.txt";
                }
                if (string.IsNullOrEmpty(mDataFilesInfo.CustomersFile))
                {
                    mDataFilesInfo.CustomersFile = "customersInfo.txt";
                }
                if (string.IsNullOrEmpty(mDataFilesInfo.PurchasedItemsFile))
                {
                    mDataFilesInfo.PurchasedItemsFile = "purchasedItems.txt";
                }

                using (FileStream fs = new FileStream(dataFileFolder + mDataFilesInfo.SportsItemsFile,
                    FileMode.Create))
                {
                    // TODO: write sports items out to the file using FileWriter
                }
                using (FileStream fs = new FileStream(dataFileFolder + mDataFilesInfo.CustomersFile,
                    FileMode.Create))
                {
                    // TODO: write customser out to the file using FileWriter
                }
                using (FileStream fs = new FileStream(dataFileFolder + mDataFilesInfo.PurchasedItemsFile,
                    FileMode.Create))
                {
                    // TODO: write puchased items out to the file using FileWriter
                }
            }
        }

        /*
         * save the dataset AS ...
         */
        private void toolStripMenuItem4_Click(object sender, EventArgs e)
        {
            SaveProjectAtSpecificLocation();
        }

        private void btnHome_tabSportsItems_Click(object sender, EventArgs e)
        {
            /*
             * select the 1st tab
             */
            tabctlMain.SelectedIndex = 0;
        }

        private void btnHome_tabCustomers_Click(object sender, EventArgs e)
        {
            /*
             * select the 1st tab
             */
            tabctlMain.SelectedIndex = 0;
        }

        private void btnHome_tabPCustomerActs_Click(object sender, EventArgs e)
        {
            /*
             * select the 1st tab
             */
            tabctlMain.SelectedIndex = 0;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            /*
             * select the 1st tab
             */
            tabctlMain.SelectedIndex = 0;
        }

        private void MenuLog_Click(object sender, EventArgs e)
        {

        }

        private void btnCustomerAct_Click(object sender, EventArgs e)
        {
            /*
             * select the 4th tab
             */
            tabctlMain.SelectedIndex = 3;
        }

        private void btnMonthlyAct_Click(object sender, EventArgs e)
        {
            /*
             * select the 5th tab
             */
            tabctlMain.SelectedIndex = 4;
        }

        private void btnClear_tabSportsItems_Click(object sender, EventArgs e)
        {
        }

        private SportsItem GetSportsItemByIndex(int index)
        {
            switch (mSportsItemsOrder)
            {
                case SportsItemsOrder.ById:
                    return mSportsStore.GetItemByIndexForId(index);
                case SportsItemsOrder.ByName:
                    return mSportsStore.GetItemByIndexForName(index);
                case SportsItemsOrder.ByDescription:
                    return mSportsStore.GetItemByIndexForDescription(index);
                case SportsItemsOrder.ByPrice:
                    return mSportsStore.GetItemByIndexForDescription(index);
                default:
                    throw new ApplicationException("Unknown order type");
            }
        }

        private CustomersItem GetCustomerItemByIndex(int index)
        {
              switch (mCustomersOrder)
            {
                case CustomersOrder.ById:
                    return mCustomers.GetItemByIndexerForId(index);
                case CustomersOrder.ByName:
                    return mCustomers.GetItemByIndexerForName(index);
                case CustomersOrder.ByAddress:
                    return mCustomers.GetItemByIndexerForName(index);
                  case CustomersOrder.ByPhone:
                    return mCustomers.GetItemByIndexerForPhone(index);
                default:
                    throw new ApplicationException("Unknown order type");
            }
        }

        private void lstItems_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = lstItems.SelectedIndex;

            SportsItem item = GetSportsItemByIndex(index);
            string name = item.Name;

            /*
             * <comments>
             *  Set the image for preview
             *  check the existence first
             *  because not every item has got its image
             * </comments>
             */

            if (mImageDictionary.ContainsKey(name))
            {
                pbxPreview.Image = mImageDictionary[name];
            }
            else
            {
                pbxPreview.Image = null;
            }

            if (!mNoSelectBack)
            {
                mNoSelectBack = true;
                cmbItemID.SelectedIndex = index;
                mNoSelectBack = false;
            }

            /*txtItemDetails
             * details
             * we use string builder to concatenate the strings
             */
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("[ID]");
            sb.AppendLine(item.Id);
            sb.AppendLine();
            sb.AppendLine("[Name]");
            sb.AppendLine(item.Name);
            sb.AppendLine();
            sb.AppendLine("[Description]");
            sb.AppendLine(item.Description);
            sb.AppendLine();
            sb.AppendLine("[Price]");
            sb.AppendLine(item.PriceString);

            txtItemDetails.Text = sb.ToString();
        }

        private void listCustomers_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = listCustomers.SelectedIndex;
            CustomersItem cItem = GetCustomerItemByIndex(index);
            string name = cItem.CustName;

            if (!mNoSelectBack)
            {
                mNoSelectBack = true;
                cmbItemID.SelectedIndex = index;
                mNoSelectBack = false;
            }
            /*
             * details
             * we use string builder to concatenate the strings
             */
            StringBuilder cb = new StringBuilder();
            cb.AppendLine("[ID]");
            cb.AppendLine(Convert.ToString(cItem.CustId));
            cb.AppendLine();
            cb.AppendLine("[Name]");
            cb.AppendLine(cItem.CustName);
            cb.AppendLine();
            cb.AppendLine("[Address]");
            cb.AppendLine(cItem.CustAddress);
            cb.AppendLine();
            cb.AppendLine("[Phone]");
            cb.AppendLine(cItem.PhoneToString(cItem.CustPhone));
            txtCustomerDetails.Text = cb.ToString();
        }

        private void cmbCustomerID_tabCustActs_SelectedIndexChanged(object sender, EventArgs e)
        {
           string selText = Convert.ToString(this.cmbCustomerID_tabCustActs.SelectedItem);
            if (!mNoSelectBack)
            {
                mNoSelectBack = true;
                mNoSelectBack = false;
            }
            ArrayList result = new ArrayList();
            result.Add(mPurchasedStore.GetItemsByCustId(selText));
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < result.Count;  i++)
             txtCustomerAct.Text += result[i]; 
        }

        private void btnByItemName_Click(object sender, EventArgs e)
        {
            /*
             * set the order type first
             * it will determine how items are loaded into the listbox
             */
            mSportsItemsOrder = SportsItemsOrder.ByName;
            ReloadSportsItems();
        }

        private void btnByItemId_Click(object sender, EventArgs e)
        {
            /*
             * set the order type first
             * it will determine how items are loaded into the listbox
             */
            mSportsItemsOrder = SportsItemsOrder.ById;
            ReloadSportsItems();
        }

        private void ByItemPrice_Click(object sender, EventArgs e)
        {
            /*
             * set the order type first
             * it will determine how items are loaded into the listbox
             */
            mSportsItemsOrder = SportsItemsOrder.ByPrice;
            ReloadSportsItems();
        }

        private void tabHome_Click(object sender, EventArgs e)
        {

        }

        private void btnById_Click(object sender, EventArgs e)
        {
            /*
           * set the order type first
           * it will determine how items are loaded into the listbox
           */
            mCustomersOrder = CustomersOrder.ById;
            ReloadCustomersItems();
        }

        private void btnByCustName_Click(object sender, EventArgs e)
        {
            mCustomersOrder = CustomersOrder.ByName;
            ReloadCustomersItems();
        }

        private void btnByCustAddress_Click(object sender, EventArgs e)
        {
            mCustomersOrder = CustomersOrder.ByAddress;
            ReloadCustomersItems();
        }

    }
}
